package com.jacklei.ch05;

import com.jacklei.tree.BinaryTree;
import com.sun.corba.se.spi.legacy.connection.GetEndPointInfoAgainException;
import sun.reflect.generics.tree.Tree;

import java.util.*;

/*
* 给你二叉树的根节点 root ，返回其节点值的 层序遍历 。 （即逐层地，从左到右访问所有节点）。

 

示例 1：


输入：root = [3,9,20,null,null,15,7]
输出：[[3],[9,20],[15,7]]
示例 2：

输入：root = [1]
输出：[[1]]
示例 3：

输入：root = []
输出：[]
 

提示：

树中节点数目在范围 [0, 2000] 内
-1000 <= Node.val <= 1000

来源：力扣（LeetCode）
链接：https://leetcode.cn/problems/binary-tree-level-order-traversal
著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。*/
public class BinaryTreeLevelOrderTraversal {
    public static void main(String[] args) {
        TreeNode root = new TreeNode(1);
        root.left = new TreeNode(2);
        root.right = new TreeNode(3);
        //root.left.left = new TreeNode(4);
        root.left.right = new TreeNode(5);
        root.right.left = new TreeNode(6);
        root.right.right = new TreeNode(7);
        BinaryTreeLevelOrderTraversal b = new BinaryTreeLevelOrderTraversal();
        List<List<Integer>> lists = b.levelOrder(null);
        for (List<Integer> list : lists) {
            for (Integer integer : list) {
                System.out.print(integer);
            }
            System.out.println();
        }
    }
    public List<List<Integer>> levelOrder1(TreeNode root) {
        List<List<Integer>> ans = new ArrayList<>();
        if(root == null) return ans;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()){
            List<Integer> in = new ArrayList<>();
            int curSize = queue.size();
            for (int i = 0; i < curSize; i++) {
                TreeNode poll = queue.poll();
                in.add(poll.val);

                if(poll.left != null) queue.add(poll.left);
                if(poll.right != null) queue.add(poll.right);
            }
            ans.add(in);
        }
        return ans;
    }
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> ans = new ArrayList<>();
        Queue<TreeNode> queue = new LinkedList<>();
        HashSet<TreeNode> set = new HashSet<>();
        TreeNode cur = root;
        while (cur != null){
            set.add(cur);
            cur = cur.left;
        }
        getEndPoint(root,set,1);
        queue.add(root);
        List<Integer> in = new ArrayList<>();
        while (!queue.isEmpty()){
            TreeNode poll = queue.poll();
            if(poll != null) {
                if (set.contains(poll)) {
                    // 当前节点根的左树集合
                    ans.add(in);
                    in = new ArrayList<>();
                }
                in.add(poll.val);
                if (poll.left != null)
                    queue.add(poll.left);
                if (poll.right != null)
                    queue.add(poll.right);
            }

        }
        if(ans.size() != 0){
        ans.remove(0);
        ans.add(in);}

        return ans;
    }

    private void getEndPoint(TreeNode root, HashSet list, int high) {
        if(root == null) return;
        if(high > list.size()) list.add(root);
        getEndPoint(root.left,list,high+1);
        getEndPoint(root.right,list,high+1);
    }

}
class TreeNode {
     int val;
     TreeNode left;
     TreeNode right;
     TreeNode() {}
     TreeNode(int val) { this.val = val; }
     TreeNode(int val, TreeNode left, TreeNode right) {
         this.val = val;
         this.left = left;
         this.right = right;
     }
 }